// ==UserScript==
// @name         网页小字提示工具
// @namespace    http://tampermonkey.net/
// @version      2.0
// @description  在网页中的小字元素上显示红色边框（不改变元素宽度），并在鼠标悬停时弹出放大内容面板，可调节最小文字长度且智能只为最内层元素添加红框
// @author       Trae
// @match        *://*/*
// @match        *://*
// @exclude      about:blank
// @grant        none
// ==/UserScript==


(function () {
    'use strict';

    // 配置常量
    const CONFIG = {
        scaleRatio: 2,                 // 放大比例
        defaultTargetFontSize: 12,     // 默认需要放大的字号大小
        panelHideTimeout: 400,         // 面板隐藏超时时间（毫秒）
        defaultMinTextLength: 8,       // 默认应用红框的最小文字长度
        precision: 0.01,               // 字体大小比较精度
        debounceTime: 300,             // DOM变化防抖时间（毫秒）
        // 需要跳过处理的元素类型
        skippedElementTypes: ['script', 'style', 'noscript', 'canvas', 'svg', 'input', 'textarea', 'select', 'option', 'button'],
        // 行内元素类型列表，需要调整display属性
        inlineElementTypes: ['span', 'a', 'strong', 'em', 'b', 'i', 'u', 'code', 'kbd', 'samp']
    };

    // 全局变量
    let targetFontSizeNumber = CONFIG.defaultTargetFontSize;
    let minTextLength = CONFIG.defaultMinTextLength;
    let popupPanel = null;          // 弹出面板元素
    let settingsPanel = null;       // 设置面板元素
    let settingsToggle = null;      // 设置按钮元素
    let fontSizeInput = null;       // 字体大小输入框
    let minTextLengthInput = null;  // 最小文字长度输入框
    
    // 状态管理
    const activeElements = new Map();     // 跟踪当前活动的元素
    let hidePanelTimeout = null;          // 面板隐藏计时器ID
    let mutationTimeout = null;           // DOM变化防抖计时器ID

    // 全局配置常量中添加scaleRatio变量引用
    const scaleRatio = CONFIG.scaleRatio;
    
    // 创建弹出面板函数
    function createPopupPanel() {
        if (!popupPanel) {
            popupPanel = document.createElement('div');
            popupPanel.style.position = 'fixed';
            popupPanel.style.background = 'rgba(255, 255, 255, 0.95)';
            popupPanel.style.border = '2px solid #ff6700';
            popupPanel.style.borderRadius = '4px';
            popupPanel.style.padding = '10px';
            popupPanel.style.zIndex = '9999';
            popupPanel.style.boxShadow = '0 4px 12px rgba(0, 0, 0, 0.15)';
            popupPanel.style.display = 'none';
            popupPanel.style.maxWidth = '80%'; // 使用视口宽度的百分比，增加面板宽度
            popupPanel.style.width = 'fit-content'; // 根据内容自适应宽度
            popupPanel.style.minWidth = '200px'; // 设置最小宽度
            popupPanel.style.wordBreak = 'break-word';
            popupPanel.style.fontWeight = '500';
            popupPanel.style.lineHeight = '1.5';
            // 添加最大高度和垂直滚动条
            popupPanel.style.maxHeight = '300px';
            popupPanel.style.overflowY = 'auto';
            
            // 添加ID方便调试
            popupPanel.id = 'small-font-popup-panel';

            // 添加鼠标移入移出事件
            popupPanel.addEventListener('mouseenter', function () {
                // 清除隐藏计时器，保持面板显示
                if (hidePanelTimeout) {
                    clearTimeout(hidePanelTimeout);
                    hidePanelTimeout = null;
                }

                if (popupPanel.currentSpanElement) {
                    activeElements.set(popupPanel.currentSpanElement, true);
                }
            });

            popupPanel.addEventListener('mouseleave', function () {
                hidePopupPanel();
            });

            document.body.appendChild(popupPanel);
        }
        
        // 每次获取面板时更新字体大小，确保使用最新配置
        popupPanel.style.fontSize = `${targetFontSizeNumber * scaleRatio}px`;
        
        return popupPanel;
    }

    // 隐藏面板的函数
    function hidePopupPanel() {
        // 清除之前的延迟计时器
        if (hidePanelTimeout) {
            clearTimeout(hidePanelTimeout);
            hidePanelTimeout = null;
        }

        // 检查是否有当前关联的元素
        if (popupPanel && popupPanel.currentSpanElement) {
            // 检查鼠标是否仍在元素上
            if (popupPanel.currentSpanElement.matches(':hover')) {
                // 鼠标仍在元素上，不隐藏面板
                return;
            }

            // 设置延迟后隐藏面板
            hidePanelTimeout = setTimeout(() => {
                if (popupPanel && popupPanel.currentSpanElement) {
                    // 再次检查鼠标是否仍在元素或面板上
                    if (!popupPanel.currentSpanElement.matches(':hover') && !popupPanel.matches(':hover')) {
                        // 移除当前活动元素的标记
                        activeElements.delete(popupPanel.currentSpanElement);
                        popupPanel.currentSpanElement = null;
                        popupPanel.style.display = 'none';
                    }
                    hidePanelTimeout = null;
                }
            }, CONFIG.panelHideTimeout);
        } else if (popupPanel) {
            // 如果没有关联元素但面板仍然可见，强制隐藏
            popupPanel.style.display = 'none';
        }
    }
    
    // 添加全局错误处理，确保面板功能稳定
    window.addEventListener('error', function(e) {
        console.error('[小字提示] 发生错误:', e.message, e.error);
        // 发生错误时重置面板状态
        if (hidePanelTimeout) {
            clearTimeout(hidePanelTimeout);
            hidePanelTimeout = null;
        }
        if (popupPanel) {
            popupPanel.style.display = 'none';
        }
    });

    // 处理包含br标签的内容
    function processContent(element) {
        try {
            // 创建一个临时div用于处理内容
            const tempDiv = document.createElement('div');
            // 防止XSS攻击，先进行基本的文本清理
            const safeText = element.textContent || '';
            
            // 如果元素有br标签，特殊处理保留换行
            if (element.innerHTML && element.innerHTML.includes('<br')) {
                // 对于包含br标签的内容，保留br标签但移除其他HTML
                tempDiv.innerHTML = element.innerHTML.replace(/<[^br][^>]*>/gi, '');
                
                // 清理后的内容
                const processedNodes = Array.from(tempDiv.childNodes).map(node => {
                    if (node.nodeType === Node.TEXT_NODE) {
                        return document.createTextNode(node.textContent);
                    } else if (node.tagName && node.tagName.toLowerCase() === 'br') {
                        return document.createElement('br');
                    } else {
                        // 对于其他元素，仅保留其文本内容
                        return document.createTextNode(node.textContent || '');
                    }
                });

                // 创建新的内容div
                const contentDiv = document.createElement('div');
                processedNodes.forEach(node => {
                    if (node) contentDiv.appendChild(node);
                });

                return contentDiv.innerHTML || safeText;
            } else {
                // 简单文本内容直接返回
                return safeText;
            }
        } catch (error) {
            console.error('[小字提示] 处理内容时发生错误:', error);
            // 出错时返回元素的文本内容作为后备
            return element.textContent || '';
        }
    }

    // 智能计算面板位置
    function calculateOptimalPosition(element, panel) {
        const rect = element.getBoundingClientRect();
        const viewportWidth = window.innerWidth;
        const viewportHeight = window.innerHeight;

        // 强制布局刷新，确保获取准确的面板尺寸
        panel.style.visibility = 'hidden';
        panel.style.display = 'block';

        // 获取准确的面板尺寸
        let panelWidth = panel.offsetWidth || Math.min(viewportWidth * 0.8, 800); // 默认为视口宽度的80%或800px，取较小值
        let panelHeight = panel.offsetHeight || 300; // 默认为最大高度
        const spacing = 4; // 面板与元素之间的间距（像素）

        // 恢复面板状态
        panel.style.display = 'none';
        panel.style.visibility = 'visible';
        
        // 确保面板尺寸有效
        if (isNaN(panelWidth) || panelWidth <= 0) {
            panelWidth = Math.min(viewportWidth * 0.8, 800);
        }
        if (isNaN(panelHeight) || panelHeight <= 0) {
            panelHeight = 300;
        }

        // 计算各个位置的可用空间
        const availableSpace = {
            right: viewportWidth - rect.right,
            left: rect.left,
            top: rect.top,
            bottom: viewportHeight - rect.bottom
        };

        // 创建位置候选列表
        const positions = [];

        // 对于视口角落的特殊处理：降低优先级位置的面板宽度要求，确保面板能显示
        const cornerTolerance = 50; // 角落容差像素值
        const isNearTopRightCorner = rect.right > viewportWidth - cornerTolerance && rect.top < cornerTolerance;
        const isNearBottomRightCorner = rect.right > viewportWidth - cornerTolerance && rect.bottom > viewportHeight - cornerTolerance;
        const isNearTopLeftCorner = rect.left < cornerTolerance && rect.top < cornerTolerance;
        const isNearBottomLeftCorner = rect.left < cornerTolerance && rect.bottom > viewportHeight - cornerTolerance;

        // 角落元素面板宽度调整
        let adjustedPanelWidth = panelWidth;
        if (isNearTopRightCorner || isNearBottomRightCorner || isNearTopLeftCorner || isNearBottomLeftCorner) {
            adjustedPanelWidth = Math.min(panelWidth, viewportWidth * 0.7); // 角落元素使用较小的面板宽度
        }

        // 右侧位置
        if (availableSpace.right >= adjustedPanelWidth) {
            positions.push({
                side: 'right',
                left: rect.right + spacing,
                top: rect.top,
                priority: 1 // 优先考虑右侧
            });
        }

        // 左侧位置
        if (availableSpace.left >= adjustedPanelWidth) {
            positions.push({
                side: 'left',
                left: rect.left - adjustedPanelWidth - spacing,
                top: rect.top,
                priority: 2
            });
        }

        // 下方位置
        if (availableSpace.bottom >= panelHeight) {
            positions.push({
                side: 'bottom',
                left: Math.max(0, Math.min(rect.left, viewportWidth - adjustedPanelWidth)),
                top: rect.bottom + spacing,
                priority: 3
            });
        }

        // 上方位置
        if (availableSpace.top >= panelHeight) {
            positions.push({
                side: 'top',
                left: Math.max(0, Math.min(rect.left, viewportWidth - adjustedPanelWidth)),
                top: rect.top - panelHeight - spacing,
                priority: 4
            });
        }

        // 如果有多个候选位置，按照优先级排序
        if (positions.length > 0) {
            positions.sort((a, b) => a.priority - b.priority);
            const bestPosition = positions[0];

            // 确保位置不会超出视口
            bestPosition.left = Math.max(0, Math.min(bestPosition.left, viewportWidth - adjustedPanelWidth));
            bestPosition.top = Math.max(0, Math.min(bestPosition.top, viewportHeight - panelHeight));

            return bestPosition;
        }

        // 如果没有理想位置，根据元素所在角落提供更智能的默认位置
        let defaultLeft, defaultTop;

        if (isNearTopRightCorner) {
            // 右上角元素，面板优先显示在左下方
            defaultLeft = Math.max(0, rect.left - adjustedPanelWidth);
            defaultTop = rect.bottom + spacing;
        } else if (isNearBottomRightCorner) {
            // 右下角元素，面板优先显示在左上方
            defaultLeft = Math.max(0, rect.left - adjustedPanelWidth);
            defaultTop = Math.max(0, rect.top - panelHeight);
        } else if (isNearTopLeftCorner) {
            // 左上角元素，面板优先显示在右下方
            defaultLeft = rect.right + spacing;
            defaultTop = rect.bottom + spacing;
        } else if (isNearBottomLeftCorner) {
            // 左下角元素，面板优先显示在右上方
            defaultLeft = rect.right + spacing;
            defaultTop = Math.max(0, rect.top - panelHeight);
        } else {
            // 其他位置，使用原有逻辑
            defaultLeft = Math.max(0, Math.min(rect.right + spacing, viewportWidth - adjustedPanelWidth));
            defaultTop = Math.max(0, Math.min(rect.top, viewportHeight - panelHeight));
        }

        return {
            left: defaultLeft,
            top: defaultTop
        };
    }

    // 创建设置面板
    function createSettingsPanel() {
        // 创建设置按钮
        settingsToggle = document.createElement('div');
        settingsToggle.style.position = 'fixed';
        settingsToggle.style.bottom = '20px';
        settingsToggle.style.right = '20px';
        settingsToggle.style.width = '50px';
        settingsToggle.style.height = '50px';
        settingsToggle.style.background = '#ff6700';
        settingsToggle.style.borderRadius = '50%';
        settingsToggle.style.color = 'white';
        settingsToggle.style.display = 'flex';
        settingsToggle.style.alignItems = 'center';
        settingsToggle.style.justifyContent = 'center';
        settingsToggle.style.cursor = 'pointer';
        settingsToggle.style.zIndex = '10000';
        settingsToggle.style.boxShadow = '0 4px 12px rgba(0, 0, 0, 0.2)';
        settingsToggle.style.fontSize = `${targetFontSizeNumber}px`;
        settingsToggle.textContent = '⚙️';

        // 创建设置面板
        settingsPanel = document.createElement('div');
        settingsPanel.style.position = 'fixed';
        settingsPanel.style.bottom = '80px';
        settingsPanel.style.right = '20px';
        settingsPanel.style.background = 'white';
        settingsPanel.style.border = '1px solid #ddd';
        settingsPanel.style.borderRadius = '8px';
        settingsPanel.style.padding = '20px';
        settingsPanel.style.zIndex = '10000';
        settingsPanel.style.boxShadow = '0 4px 12px rgba(0, 0, 0, 0.15)';
        settingsPanel.style.display = 'none';
        settingsPanel.style.minWidth = '250px';

        // 添加标题
        const title = document.createElement('h3');
        title.style.margin = '0 0 15px 0';
        title.style.color = '#333';
        title.textContent = '网页小字提示工具设置';
        settingsPanel.appendChild(title);

        // 添加需要放大的字号大小设置
        const fontSizeContainer = document.createElement('div');
        fontSizeContainer.style.marginBottom = '15px';

        const fontSizeLabel = document.createElement('label');
        fontSizeLabel.style.display = 'block';
        fontSizeLabel.style.marginBottom = '5px';
        fontSizeLabel.style.color = '#666';
        fontSizeLabel.textContent = '需要放大的字号大小 (px)';
        fontSizeContainer.appendChild(fontSizeLabel);

        fontSizeInput = document.createElement('input');
        fontSizeInput.type = 'number';
        fontSizeInput.value = targetFontSizeNumber;
        fontSizeInput.min = '1';
        fontSizeInput.step = '1';
        fontSizeInput.style.width = '100%';
        fontSizeInput.style.padding = '8px';
        fontSizeInput.style.border = '1px solid #ddd';
        fontSizeInput.style.borderRadius = '4px';
        fontSizeInput.style.boxSizing = 'border-box';
        fontSizeContainer.appendChild(fontSizeInput);

        settingsPanel.appendChild(fontSizeContainer);

        // 添加最小文字长度设置
        const minTextLengthContainer = document.createElement('div');
        minTextLengthContainer.style.marginBottom = '15px';

        const minTextLengthLabel = document.createElement('label');
        minTextLengthLabel.style.display = 'block';
        minTextLengthLabel.style.marginBottom = '5px';
        minTextLengthLabel.style.color = '#666';
        minTextLengthLabel.textContent = '最小文字长度 (字符)';
        minTextLengthContainer.appendChild(minTextLengthLabel);

        minTextLengthInput = document.createElement('input');
        minTextLengthInput.type = 'number';
        minTextLengthInput.value = minTextLength;
        minTextLengthInput.min = '1';
        minTextLengthInput.step = '1';
        minTextLengthInput.style.width = '100%';
        minTextLengthInput.style.padding = '8px';
        minTextLengthInput.style.border = '1px solid #ddd';
        minTextLengthInput.style.borderRadius = '4px';
        minTextLengthInput.style.boxSizing = 'border-box';
        minTextLengthContainer.appendChild(minTextLengthInput);

        settingsPanel.appendChild(minTextLengthContainer);

        // 添加应用按钮
        const applyButton = document.createElement('button');
        applyButton.textContent = '应用设置';
        applyButton.style.width = '100%';
        applyButton.style.padding = '10px';
        applyButton.style.background = '#ff6700';
        applyButton.style.color = 'white';
        applyButton.style.border = 'none';
        applyButton.style.borderRadius = '4px';
        applyButton.style.cursor = 'pointer';
        applyButton.style.fontSize = '14px';
        applyButton.addEventListener('click', applySettings);
        settingsPanel.appendChild(applyButton);

        // 添加重置按钮
        const resetButton = document.createElement('button');
        resetButton.textContent = '重置';
        resetButton.style.width = '100%';
        resetButton.style.marginTop = '10px';
        resetButton.style.padding = '10px';
        resetButton.style.background = '#f5f5f5';
        resetButton.style.color = '#666';
        resetButton.style.border = '1px solid #ddd';
        resetButton.style.borderRadius = '4px';
        resetButton.style.cursor = 'pointer';
        resetButton.style.fontSize = '14px';
        resetButton.addEventListener('click', function () {
            fontSizeInput.value = targetFontSizeNumber;
            minTextLengthInput.value = minTextLength; // 重置为默认值
            applySettings();
        });
        settingsPanel.appendChild(resetButton);

        // 切换设置面板显示/隐藏
        settingsToggle.addEventListener('click', function () {
            if (settingsPanel.style.display === 'none' || settingsPanel.style.display === '') {
                settingsPanel.style.display = 'block';
            } else {
                settingsPanel.style.display = 'none';
            }
        });

        // 点击面板外部关闭面板
        document.addEventListener('click', function (event) {
            if (settingsPanel && settingsPanel.style.display === 'block' && !settingsPanel.contains(event.target)
                && settingsToggle && !settingsToggle.contains(event.target)) {
                settingsPanel.style.display = 'none';
            }
        });

        // 添加到文档中
        document.body.appendChild(settingsToggle);
        document.body.appendChild(settingsPanel);
    }

    // 计算元素的嵌套深度
    function getElementDepth(element) {
        let depth = 0;
        let current = element.parentElement;
        while (current && current !== document.body) {
            depth++;
            current = current.parentElement;
        }
        return depth;
    }

    // 判断元素是否是叶级文本元素
    // 只基于DOM结构树判断，不考虑字体大小
    function isLeafTextElement(element) {
        // 如果元素没有子元素，它肯定是叶元素
        if (element.children.length === 0) {
            return true;
        }

        // 定义非文本容器元素（这些元素不会包含需要独立处理的文本内容）
        const nonTextContainerElements = ['br', 'hr', 'img', 'input', 'button', 'select', 'textarea', 'script', 'style', 'link', 'meta'];

        // 检查所有子元素
        for (let i = 0; i < element.children.length; i++) {
            const child = element.children[i];
            const childTagName = child.tagName.toLowerCase();

            // 如果子元素不是非文本容器元素，并且有文本内容，则当前元素不是叶元素
            if (!nonTextContainerElements.includes(childTagName) && child.textContent.trim().length > 0) {
                return false;
            }
        }

        // 如果所有子元素都是非文本容器元素或者没有文本内容，则当前元素是叶元素
        return true;
    }

    // 应用设置
    function applySettings() {
        const newFontSize = parseFloat(fontSizeInput.value);
        const newMinTextLength = parseFloat(minTextLengthInput.value);

        let isValid = true;
        let errorMessage = '';

        // 验证字体大小
        if (isNaN(newFontSize) || newFontSize < 1) {
            isValid = false;
            errorMessage = '请输入大于1的有效数字作为字体大小';
        }

        // 验证最小文字长度
        if (isValid && (isNaN(newMinTextLength) || newMinTextLength < 1)) {
            isValid = false;
            errorMessage = '请输入大于1的有效数字作为最小文字长度';
        }

        if (isValid) {
            // 应用字体大小设置
            targetFontSizeNumber = newFontSize;
            // 应用最小文字长度设置
            minTextLength = newMinTextLength;

            // 更新弹出面板的字体大小
            if (popupPanel) {
                popupPanel.style.fontSize = `${targetFontSizeNumber * scaleRatio}px`;
            }

            // 重新处理所有元素
            resetAndProcessAllElements();

            console.log(`需要放大的字号大小已更新为: ${newFontSize + 'px'}, 最小文字长度已更新为: ${minTextLength}字符`);
            console.log(`系统将为所有字体大小≤${newFontSize}px且文本长度≥${minTextLength}字符的元素添加红框`);
        } else {
            alert(errorMessage);
            fontSizeInput.value = targetFontSizeNumber;
            minTextLengthInput.value = minTextLength;
        }
    }

    // 重置并重新处理所有元素
    function resetAndProcessAllElements() {
        // 移除所有已处理元素的标记和样式，但跳过设置面板和弹出面板相关元素
        const processedElements = document.querySelectorAll('[data-small-text-processed="true"]');
        processedElements.forEach(element => {
            // 检查元素是否与设置面板或弹出面板相关，如果相关则跳过
            // 确保在调用contains方法前检查变量是否为null
            if ((settingsPanel && (element === settingsPanel || settingsPanel.contains(element)))
                || (settingsToggle && (element === settingsToggle || settingsToggle.contains(element)))
                || (popupPanel && (element === popupPanel || popupPanel.contains(element)))) {
                return;
            }

            element.removeAttribute('data-small-text-processed');
            element.style.border = '';
            element.style.borderRadius = '';
            element.style.display = '';
            element.style.outline = '';
            element.style.outlineOffset = '';
            element.style.boxSizing = '';
        });

        // 隐藏当前面板
        if (popupPanel) {
            popupPanel.style.display = 'none';
        }

        // 清空活动元素跟踪
        activeElements.clear();

        // 重新处理所有元素
        processElements();
    }

    // 处理元素的函数
    function processElements() {
        
        // 获取所有元素
        const allElements = document.querySelectorAll('body *');
        let processedCount = 0;
        let skippedCount = 0;

        // 创建一个数组并按照嵌套深度降序排序（最深的元素排前面）
        // 这样我们先处理最内层元素，再处理外层元素
        const elementsArray = Array.from(allElements).sort((a, b) => {
            const depthA = getElementDepth(a);
            const depthB = getElementDepth(b);
            return depthB - depthA;
        });

        // 遍历所有元素检查字体大小
        for (let element of elementsArray) {
            // 跳过一些不应该处理的元素类型
            const tagName = element.tagName.toLowerCase();
            if (CONFIG.skippedElementTypes.includes(tagName)) {
                skippedCount++;
                continue;
            }

            // 跳过设置面板相关元素，确保在调用contains方法前检查变量是否为null
            if ((settingsPanel && (element === settingsPanel || settingsPanel.contains(element)))
                || (settingsToggle && (element === settingsToggle || settingsToggle.contains(element)))) {
                skippedCount++;
                continue;
            }

            // 跳过弹出面板自身
            // 确保element是有效的DOM元素再调用contains方法
            if (element === popupPanel || (element && popupPanel && element.contains(popupPanel))) {
                skippedCount++;
                continue;
            }

            // 获取字体大小的多种方式，以解决浏览器最小字体限制问题
            let fontSizeValue = 0;
            
            // 优化: 先检查元素是否为空或不可见，快速跳过不需要处理的元素
            if (!element.textContent.trim() || 
                (element.offsetWidth === 0 && element.offsetHeight === 0)) {
                skippedCount++;
                continue;
            }
            
            // 方式1: 从element的style属性直接获取（如果有内联样式）
            const inlineFontSize = element.style.fontSize;
            if (inlineFontSize && inlineFontSize.trim() !== '') {
                const inlineSize = parseFloat(inlineFontSize);
                if (!isNaN(inlineSize)) {
                    fontSizeValue = inlineSize;
                }
            }
            
            // 方式2: 使用getComputedStyle获取计算后的样式
            const computedStyle = window.getComputedStyle(element);
            const computedFontSize = computedStyle.fontSize;
            const computedSize = parseFloat(computedFontSize);
            
            // 比较两种方式获取的字体大小，如果内联样式存在且小于计算后的样式，使用内联样式的值
            if (!isNaN(computedSize)) {
                if (fontSizeValue === 0 || computedSize < fontSizeValue) {
                    fontSizeValue = computedSize;
                }
            }
            
            // 确保字体大小值有效
            if (isNaN(fontSizeValue) || fontSizeValue === 0) {
                fontSizeValue = 16; // 默认字体大小
            }

            // 使用配置中的精度阈值
            
            // 检查字号是否过小并且尚未处理过
            // 添加文本长度检查和子元素检查（确保只为最内层元素添加红框）
            // 直接使用 <= 比较并考虑精度，确保小数像素值在目标大小及以下时也能被正确检测
            const shouldProcess = 
                (fontSizeValue <= targetFontSizeNumber + CONFIG.precision) && // 允许微小的精度误差
                !element.hasAttribute('data-small-text-processed')
                && element.textContent.trim().length >= minTextLength
                && isLeafTextElement(element);
                
            // 添加详细的调试信息，帮助诊断问题
            // if (isLeafTextElement(element) && element.tagName.toLowerCase() == 'span') {
            //     console.log(`[小字提示] 元素: ${element.tagName}, 计算字体大小: ${fontSizeValue.toFixed(3)}px, 目标字体大小: ${targetFontSizeNumber}px, 文本长度: ${element.textContent.trim().length}, 是否叶元素: ${isLeafTextElement(element)}, 是否处理: ${shouldProcess}，内容：${element.innerText}`);
            // }
            // if (fontSizeValue <= targetFontSizeNumber + 2) { // 对接近目标大小的元素都记录日志
            //     if (!shouldProcess) {
            //         // 如果不处理，记录具体原因
            //         let reason = '';
            //         if (fontSizeValue > targetFontSizeNumber + precision) reason = '字体大小超过目标值';
            //         else if (element.hasAttribute('data-small-text-processed')) reason = '元素已处理过';
            //         else if (element.textContent.trim().length < minTextLength) reason = '文本长度小于最小要求';
            //         else if (!isLeafTextElement(element)) reason = '不是叶级文本元素';
            //         console.log(`[小字提示] 不处理原因: ${reason}`);
            //     }
            // }
            
            if (shouldProcess) {
                // 添加标记表示已处理
                element.setAttribute('data-small-text-processed', 'true');

                // 使用outline代替border，不会改变元素宽度
                element.style.outline = '1px solid #ff0000';
                element.style.outlineOffset = '0px';
                element.style.borderRadius = '2px';
                // 设置box-sizing确保边框不会改变元素宽度
                element.style.boxSizing = 'border-box';
                // 只对行内元素调整display，避免影响布局
                if (CONFIG.inlineElementTypes.includes(tagName)) {
                    element.style.display = 'inline-block';
                }

                // 鼠标悬停时显示弹出面板
                element.addEventListener('mouseenter', function (e) {
                    // 清除隐藏计时器，防止面板被延迟隐藏
                    if (hidePanelTimeout) {
                        clearTimeout(hidePanelTimeout);
                        hidePanelTimeout = null;
                    }

                    // 获取或创建弹出面板
                    const panel = createPopupPanel();
                    
                    // 如果面板已经显示但关联的是不同元素，不需要隐藏再显示
                    // 直接更新内容和位置，实现无缝切换
                    if (panel.currentSpanElement !== null && panel.currentSpanElement !== this) {
                        // 移除旧元素的活动标记
                        activeElements.delete(panel.currentSpanElement);
                    }
                    
                    // 记录当前关联的元素
                    panel.currentSpanElement = this;
                    // 设置元素为活动状态
                    activeElements.set(this, true);
                    // 处理内容，保留br标签的换行效果
                    panel.innerHTML = processContent(this);

                    // 使用智能定位算法计算面板位置
                    const position = calculateOptimalPosition(this, panel);

                    panel.style.left = `${position.left}px`;
                    panel.style.top = `${position.top}px`;
                    
                    // 强制显示面板，添加轻微延迟确保位置计算完成
                    setTimeout(() => {
                        panel.style.display = 'block';
                    }, 10);
                });

                // 鼠标移走时设置面板在指定时间后隐藏
                element.addEventListener('mouseleave', function () {
                    // 检查鼠标是否在面板上，如果不在则设置隐藏计时器
                    if (!popupPanel || !popupPanel.matches(':hover')) {
                        hidePopupPanel();
                    }
                });
                
                processedCount++;
            }
        }
        
        if (processedCount > 0) {
            console.log(`[小字提示] 处理完成，共处理元素 ${processedCount} 个，跳过元素 ${skippedCount} 个`);
        }
    }

    // 初始加载时处理
    processElements();

    // 创建设置面板
    createSettingsPanel();

    // 优化: 防抖处理DOM变化，避免短时间内多次触发
    function debounceProcessElements() {
        if (mutationTimeout) {
            clearTimeout(mutationTimeout);
        }
        mutationTimeout = setTimeout(processElements, CONFIG.debounceTime);
    }

    // 监听页面变化，处理动态加载的内容
    const observer = new MutationObserver(function (mutations) {
        let shouldProcess = false;
        
        mutations.forEach(function (mutation) {
            // 有新节点添加时标记需要处理
            if (mutation.addedNodes.length > 0) {
                shouldProcess = true;
            }
        });
        
        if (shouldProcess) {
            debounceProcessElements();
        }
    });

    // 配置观察者监听整个文档的变化
    observer.observe(document.body, {
        childList: true,
        subtree: true
    });

    console.log(`网页小字提示工具已运行(v${GM_info.script.version})，已为所有${targetFontSizeNumber}px的文字添加了红色边框和悬停放大功能`);
})();